package net.zoneland.knowledge.service.impl.search;

import java.util.stream.Collectors;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.zoneland.knowledge.config.AopConfig;

/**
 * .
 *
 * @author: bcc
 * 2021/5/26
 */
public abstract class AbstractSearchOperation implements SearchOperation {
    /**
     * 日志.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSearchOperation.class);

    private SearchOperation nextSearchOperation;

    /**
     * 实现查询的方法.
     * @param searchDto 查询参数对象
     */
    protected abstract void doSearchOrDeal(final SearchDto searchDto) throws Exception;

    /**
     * 调用查询处理方法逻辑.
     * @param searchDto 查询参数对象
     */
    public void callSearchOrDeal(final SearchDto searchDto) throws Exception {
        if (needRun(searchDto)) {
            doSearchOrDeal(searchDto);
        }
    }

    /**
     * 判断特定场景.
     * @param searchDto 查询参数对象
     * @return 是/否
     */
    public boolean needRun(final SearchDto searchDto) {
        return true;
    }

    @Override
    public void searchOrDeal(final SearchDto searchDto) throws Exception {
        //因为doSearchOrDeal方法在类中自调用，所以spring的aop无法创建切面.
        if (AopConfig.isStopWatchEnabledConst()) {
            final StopWatch sw = StopWatch.createStarted();
            callSearchOrDeal(searchDto);
            sw.split();
            LOGGER.info("==========stop watch, instanceClass:{}, searchDto:{}, consumerTime:{}",
                this.getClass().getCanonicalName(),
                searchDto.hashCode(),
                sw.getSplitTime());
            sw.stop();
        } else {
            callSearchOrDeal(searchDto);
        }

        if (!searchDto.isStopDeal() || !searchDto.isStopSearch()) {
            if (null != nextSearchOperation) {
                nextSearchOperation.searchOrDeal(searchDto);
            }
        }

    }

    /**
     * 是否需要停止查询.
     * @param searchDto 查询参数
     * @return 是/否
     */
    protected boolean needStop(final SearchDto searchDto) {
        return CollectionUtils.isNotEmpty(searchDto.getEsQuestions());
    }

    /**
     * .
     *
     * @return nextSearchOperation
     */
    public SearchOperation getNextSearchOperation() {
        return nextSearchOperation;
    }

    /**
     * .
     *
     * @param nextSearchOperation to set
     */
    public void setNextSearchOperation(final SearchOperation nextSearchOperation) {
        this.nextSearchOperation = nextSearchOperation;
    }
}
